﻿using System.Collections.Generic;
using System.Linq;
using RouteOptimization.ModelObjects;

namespace RouteOptimization.Common.Graph
{
    public class Graph
    {
        public IList<Vertex> Vertices { get; set; }

        public IList<Edge> Edges { get; set; }
        
        /// <summary>
        /// expand graph till <para name="to">to</para> or <param name="started">started</param>
        /// e.g.   4                          3
        ///       / \                        / \
        ///      /   \                      4   2
        /// 0---1     3   from 0 to 3      /     \
        ///      \  _/                    1       1
        ///       2                      / \     / \
        ///                             0   2   4   0
        /// </summary>
        /// <param name="node"></param>
        /// <param name="from"></param>
        /// <param name="started"></param>
        /// <param name="to"></param>
        /// <param name="fromLast"></param>
        /// <returns></returns>
        public Node ExpandGraphRecursive(int fromId, int started, int to, int fromLast)
        {
            var node = new Node() {Edge = Edges.FirstOrDefault(x => x.From.Id == fromId)};
            ExpandGraphRecursiveInner(node, fromId, started, to, fromLast);
            return node;
        }

        private void ExpandGraphRecursiveInner(Node node, int from, int started, int to, int fromLast)
        {
            IList<Edge> possibleRoutes = fromLast >= 0
                                             ? Edges.Where(
                                                 x => x.From.Id == from && x.To.Id != fromLast && x.To.Id != started).
                                                   ToList()
                                             : Edges.Where(
                                                 x => x.From.Id == from).ToList();
            foreach (var possibleRoute in possibleRoutes)
            {
                node.Add(possibleRoute, to);
                ExpandGraphRecursiveInner(node, possibleRoute.To.Id, started, to, possibleRoute.From.Id);
            }
        }
    }
}